package org.qdog.pk.pkscrape.controller;

import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import org.qdog.pk.pkscrape.entity.*;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;

/**
 * @since 08/2011
 */
@Component
public class WorkMgr {
  private static final Logger LOG = Logger.getLogger(WorkMgr.class);
  private static final int STALE_KINGDOM_HOURS = 24;
  private static final int STALE_CITY_HOURS = 24*2;
  private static final int STALE_PERSON_HOURS = 24*7;

  private EntityUpdater entityUpdater;
  private EntityMgr entityMgr;
  private UrlDownloader urlDownloader;

  public void fullUpdate() {
    updateNewEntities();
    updateStaleEntities();
  }

  public void updateNewEntities() {

    Collection<EntityType> toProcess = Arrays.asList(EntityType.Kingdom, EntityType.City, EntityType.Person);
    for (EntityType type : toProcess) {
      Collection<Entity> entities = entityMgr.loadNewEntities(type);
      LOG.info("Updating " + entities.size() + " new " + type.toString() + " entities");
      updateEntities(entities);
    }
  }

  public void updateStaleEntities() {
    Collection<EntityType> toProcess = Arrays.asList(EntityType.Kingdom, EntityType.City, EntityType.Person);
    for (EntityType type : toProcess) {
      Collection<Entity> entities = entityMgr.loadStaleEntities(type, DateUtils.addHours(new Date(), type.getStaleHours() * -1));
      LOG.info("Updating " + entities.size() + " stale " + type.toString() + " entities");
      updateEntities(entities);
    }
  }

  private void updateEntities(Collection<Entity> entities) {
    for (Entity entity : entities) {
      updateEntity(entity);
    }
  }

  public void updateEntity(String entityId) {
    Entity entity = entityMgr.createOrLoadEntityById(entityId);
    updateEntity(entity);
  }

  public void updateEntity(Entity entity) {
    LOG.info("Updating " + entity.getId());
    try {
      String xml = urlDownloader.downloadEntity(entity.getId());
      if (entity instanceof City) {
        entityUpdater.updateCity((City) entity, xml);
      } else if (entity instanceof Person) {
        entityUpdater.updatePerson((Person) entity, xml);
      } else if (entity instanceof Kingdom) {
        entityUpdater.updateKingdom((Kingdom) entity, xml);
      } else {
        throw new RuntimeException("Unsupported entity type : " + entity.getClass().getName());
      }

      // TODO perform some basic validation to make sure that the entity was extracted correctly
    } catch (Exception e) {
      LOG.error("Error occurred while updating " + entity.getClass().getName() + " with id " + entity.getId(), e);
    }
  }

  @Resource(name = "entityUpdater")
  public void setEntityUpdater(EntityUpdater entityUpdater) {
    this.entityUpdater = entityUpdater;
  }

  @Resource(name = "entityMgr")
  public void setEntityMgr(EntityMgr entityMgr) {
    this.entityMgr = entityMgr;
  }

  @Resource(name = "urlDownloader")
  public void setUrlDownloader(UrlDownloader urlDownloader) {
    this.urlDownloader = urlDownloader;
  }
}
